﻿using System;
using BalanceManager.Helpers;
using BalanceManager.Model;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using BalanceManager.Services;

namespace BalanceManager.ViewModels
{
    public class ItemsViewModel : BaseViewModel, INavigable
    {
        private IDataService _dataService;

        ObservableCollection<Item> _items;
        TreeNode<Item> _itemsTree;
        private FundFlowEditableParameter fundFlowEditableParameter = null;

        public ItemsViewModel(IDataService dataService)
        {
            if (dataService == null)
                throw new ArgumentException("dataService");

            _dataService = dataService;

            _selectItemCommand = new DelegateCommand(SelectItemAction);
            _deleteItemCommand = new DelegateCommand(DeleteItemAction);

            _items = new ObservableCollection<Item>(_dataService.Items);
            _itemsTree = new TreeNode<Item>(new Item());

            BuildTree();
        }

        void BuildTree()
        {
            var rootNodes = _items.Where(i => i.ParentId == null);
            foreach (var rootNode in rootNodes)
            {
                var newNode = _itemsTree.AddChild(rootNode);
                BuildNode(newNode);
            }
        }

        void BuildNode(TreeNode<Item> rootNode)
        {
            var subNodes = _items.Where(i => i.ParentId == rootNode.Item.Id);
            foreach (var node in subNodes)
            {
                var newNode = rootNode.AddChild(node);
                BuildNode(newNode);
            }
        }

        TreeNode<Item> _selectedNode; 
        public TreeNode<Item> SelectedNode
        {
            get { return _selectedNode; }
            set
            {
                _selectedNode = value;
                OnPropertyChanged("SelectedNodePath");
                OnPropertyChanged();
            }
        }

        public string SelectedNodePath
        {
            get
            {
                if (_selectedNode == null) return "Без категории";

                var list = new List<string>();
                list.Add(_selectedNode.Item.Name);

                var parentItem = _selectedNode.Item;
                while ((parentItem = _items.FirstOrDefault(i => i.Id == parentItem.ParentId)) != null)
                {
                    list.Add(parentItem.Name);
                }

                list.Reverse();
                return string.Join(":", list);
            }
        }

        public ObservableCollection<TreeNode<Item>> ItemsTree
        {
            get { return _itemsTree.Children; }
        }

        public void AddItem(Item item)
        {
            _dataService.SaveItem(item);
            _items.Add(item);
            if (_selectedNode != null)
            {
                _selectedNode.AddChild(item);
            }
            else
            {
                _itemsTree.AddChild(item);
            }
        }

        public void EditItem(Item item)
        {
            _dataService.SaveItem(item);
            OnPropertyChanged("ItemsTree");
        }

        DelegateCommand _deleteItemCommand;

        public DelegateCommand DeleteItemCommand
        {
            get { return _deleteItemCommand; }
        }

        private void DeleteItemAction(object o)
        {
            if (!CanExecuteDeleteItemAction(o)) return;

            var item = (Item)o;
            _dataService.DeleteItem(item.Id);
            _items.Remove(item);

            if (_selectedNode == null)
            {
                ItemsTree.Remove(ItemsTree.FirstOrDefault(i => i.Item.Id == item.Id));
            }
            else
            {
                _selectedNode.Children.Remove(_selectedNode.Children.FirstOrDefault(i => i.Item.Id == item.Id));
            }

            OnPropertyChanged("ItemsTree");
            OnPropertyChanged("SelectedNode");
        }

        bool CanExecuteDeleteItemAction(object o)
        {
            if (o == null) return false;

            var item = (Item)o;
            var hasChilds = _dataService.ItemHasChilds(item);
            var hasFundFlows = _dataService.ItemExistsInFundFlows(item);
            return !hasChilds && !hasFundFlows;
        }

        bool _isSelectItemPage;
        public bool IsSelectItemPage
        {
            get
            {
                return _isSelectItemPage;
            }
            set
            {
                if (_isSelectItemPage == value) return;
                _isSelectItemPage = value;
                OnPropertyChanged();
            }
        }

        DelegateCommand _selectItemCommand;
        public DelegateCommand SelectItemCommand 
        {
            get
            {
                return _selectItemCommand;
            }
        }

        void SelectItemAction(object o)
        {
            fundFlowEditableParameter.FundFlow.ItemId = SelectedNode.Item.Id;
            fundFlowEditableParameter.FundFlow.ItemName = SelectedNode.Item.Name;
            ApplicationController.Default.NavigationParameters.Add("fundFlowParam", fundFlowEditableParameter);
            ApplicationController.Default.NavigateTo(ViewType.AddFundFlow);
            ApplicationController.Default.RemoveBackEntry();
        }

        public void Activate(IDictionary<string, object> parameters)
        {
            if (parameters.ContainsKey("fundFlowParam"))
            {
                IsSelectItemPage = true;
                fundFlowEditableParameter = (FundFlowEditableParameter)parameters["fundFlowParam"];
            }
                
        }

        public void Deactivate(IDictionary<string, object> parameters) { }
    }
}
